perm filename TABLES.FAI[HST,NET] blob sn#727529 filedate 1983-10-12 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00014 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	 A B C D E P DIN DOUT DVER PUPVER PUPEFT ERR SRINIC HNSPRT MSCSKT PDLEN BUFLEN VERFIL VERPPN HSTFIL HSTPPN DIRFIL DIRPPN ERRFIL ERRPPN NICVER DSKVER ENDMK ENDEND DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF BATCHM MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS
C00012 00003	 NETSTR NETST1 DECOUT OCTOUT OCTOU1 GETCHR BADCHR YESNO CPOPJ1 CPOPJ
C00014 00004	 MESTYP MESTY1 MAILMS ERRERR
C00017 00005	 VERNIC VERNI1 VERNI2
C00019 00006	 VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2
C00022 00007	 VERCOM VERCO1
C00023 00008	 NEWNIC NEWNI1 NEWNI2 NEWNI3
C00027 00009	 RDPDIR
C00028 00010	 GETVER GETVE1
C00032 00011	 GNPDIR GNPDI1 GNPDI2 GNPDI4 GNPDI3 GETCOR GETCO1
C00042 00012	 NICUPD NICUP1 NICERR
C00045 00013	 PUPUPD PUPERR
C00047 00014	 UPDATE NOERRS
C00049 ENDMK
C⊗;
;⊗ A B C D E P DIN DOUT DVER PUPVER PUPEFT ERR SRINIC HNSPRT MSCSKT PDLEN BUFLEN VERFIL VERPPN HSTFIL HSTPPN DIRFIL DIRPPN ERRFIL ERRPPN NICVER DSKVER ENDMK ENDEND DIRHLN DIRHDR VERPTR VERLSN VERSTS VERTRM VERCON VCNSTS VERHST EFTGEN EFTGSK EFTLSN EFTSTS EFTLSK EFTHST PUPMAX PKTBUF PKTLEN PKTTYP PKTDST PKTSRC PKTBFD PUPOVH OURHST PUPDSV PUPMSV PUPMHS PDL DIBUF DOBUF DVIBUF DVOBUF PUPIBF ERBUF ERRORS CHANGE CRLF BATCHM MAIHD1 MAIHD2 MAIHD3 MAIBLK NIORTS

	TITLE TABLES

;WAITS program to automatically update NIC and PUP host tables.
;Joe Weening, SU-AI, September 1983.

;Currently, this program does the following:
;1. Gets the current version number of the NIC host table from the host name
;   server at SRI-NIC, and compares it with the version number of our file.  The
;   file is HOSTS.TST[HST,NET], and the version number is stored as a character
;   string in the file HOSTS.VER[HST,NET].  If needed, a new host table is
;   retrieved from the host name server.
;2. Sends out the version number of our PUP network directory, and collects
;   replies indicating higher version numbers at other Ethernet sites.  Updates
;   the directory, kept as the binary file PUPNET.DIR[HST,NET].
;Future plans include the following:
;3. Convert the binary PUPNET.DIR to a text version in RFC810 format.  This can
;   already be done using the PUPHST program on [HST,NET].
;4. Merge the text form of the NIC and PUP tables into a binary HOSTS3-format
;   table, and store it as HOSTS3.BIN[HST,NET].  This can now be done with the
;   HOSTS3 program.

A←1				;AC definitions
B←2
C←3
D←4
E←5
P←17

;I/O channels.  0, 1, and 2 are reserved for NETWRK, used for IMP I/O.
;NETWRK is not used for PUP I/O, since it doesn't handle packet and EFTP modes.

DIN←←3				;Disk input channel
DOUT←←4				;Disk output channel
DVER←←5				;Disk channel for HOSTS.VER file
PUPVER←←6			;PUP channel for version request
PUPEFT←←7			;PUP channel for EFTP directory update
ERR←←10				;Disk channel for error message file

;Host number for SRI-NIC.  We could use HSTNAM, but then we'd lose if there was
;something wrong with the host table.
SRINIC←←<BYTE (4)0(8)=10,0,0,=51>
HNSPRT←←=101			;Host Name Server port number

;Ethernet address of preferred host for PUP net directory update
;;PRFHST←←<50⊗=8>+13		;Navajo
MSCSKT←←4			;Misc. server socket number

;Other definitions
PDLEN←←20			;Stack
BUFLEN←←40			;Length of various blocks

;LOOKUP/ENTER blocks for files

VERFIL:	SIXBIT/HOSTS/		;File with NIC version string
	SIXBIT/VER/
	0
	0
VERPPN:	SIXBIT/HSTNET/

HSTFIL:	SIXBIT/HOSTS/		;NIC host table
	SIXBIT/TXT/
	0
	0
HSTPPN:	SIXBIT/HSTNET/

DIRFIL:	SIXBIT/PUPNET/		;PUP network directory
	SIXBIT/DIR/
	0
	0
DIRPPN:	SIXBIT/HSTNET/

ERRFIL:	SIXBIT/$MAIL/		;Error message mail file
	SIXBIT/TMP/
	0
	0
ERRPPN:	SIXBIT/HSTNET/

;Data for NIC table update

NICVER:	BLOCK BUFLEN		;Version string from NIC
DSKVER:	BLOCK BUFLEN		;Version string on disk

ENDMK:	12			;Chars that mark end of NIC host table
	"E"
	"N"
	"D"
ENDEND←←.

;Definitions for reading header of PUP network directory from file

DIRHLN←←4			;Number of header words to read
DIRHDR:	BLOCK DIRHLN
VERPTR:	POINT 16,DIRHDR+3,15	;Byte ptr for version number

;MTAPE blocks for PUP operations

VERLSN:	1			;Listen block for PUP version request
VERSTS:	0			;Status bits returned
	-1			;Local socket
	0			;Don't wait
	=8			;Byte size
	MSCSKT			;Foreign socket
	-1			;Foreign host (broadcast)

VERTRM:	3			;Terminate block for PUPVER
	0			;Status
	0			;Local socket
	0			;Don't wait

VERCON:	0			;Connect block for PUPVER
VCNSTS:	0			;Status
	-1			;Local socket
	-1			;Do wait (though in packet mode we won't)
	=8			;Byte size
	MSCSKT			;Foreign socket
VERHST:	0			;Foreign host

EFTGEN:	21			;Gensym block for EFTP socket
EFTGSK:	0

EFTLSN:	1			;Listen block for EFTP
EFTSTS:	0			;Status bits returned
EFTLSK:	0			;Local socket
	0			;Don't wait
	=8			;Byte size
	-1			;Foreign socket (whatever they choose)
EFTHST:	0			;Foreign host

;Definitions for sending packet-mode PUPs

PUPMAX←←=140			;Maximum PUP packet length
PKTBUF:	BLOCK PUPMAX		;PUP packet buffer

;Pointers into PKTBUF

PKTLEN:	POINT 16,PKTBUF,15	;PUP length (in bytes)
PKTTYP:	POINT 16,PKTBUF,31	;PUP Type
PKTDST:	POINT 16,PKTBUF+2,15	;PUP Destination host
PKTSRC:	POINT 16,PKTBUF+3,31	;PUP Source host
PKTBFD←←PKTBUF+5		;Location of data within PUP
PUPOVH←←=22			;Number of overhead bytes in a PUP

;Data for PUP network directory update

OURHST:	BLOCK 1			;Our PUP address (from an incoming packet)
PUPDSV:	BLOCK 1			;PUP directory on disk's version number
PUPMSV:	BLOCK 1			;Highest version number from misc. servers
PUPMHS:	BLOCK 1			;Host number that has highest version

;Other things

PDL:	BLOCK PDLEN
DIBUF:	BLOCK 3			;Buffer headers
DOBUF:	BLOCK 3
DVIBUF:	BLOCK 3
DVOBUF:	BLOCK 3
PUPIBF:	BLOCK 3
ERBUF:	BLOCK 3
ERRORS:	0			;-1 if we have errors
CHANGE:	0			;-1 if anything changed
CRLF:	BYTE (7)15,12
BATCHM:	0			;-1 if batch mode

;Definitions for error messages

DEFINE MESSAG(MESS) <
	JRST [  MOVEI A,[ASCIZ\MESS
\]
		JRST MESTYP]
>

;Header lines for error message file
MAIHD1:	ASCIZ\MAIL/SUBJECT BUG-HOST\
MAIHD2:	BYTE (7)15,12,14	;CRLF,FF
MAIHD3:	ASCIZ/Bug report from UPDATE of host tables

/

;Data block for SWAP UUO
MAIBLK:	SIXBIT/SYS/
	SIXBIT/MAIL/
	SIXBIT/DMP/
	0,,1			;RPG startup
	0
	0

NIORTS←←-1			;Use network I/O routines for IMP
.INSERT NETWRK.FAI[S,NET]	;Wonderful network I/O package
;⊗ NETSTR NETST1 DECOUT OCTOUT OCTOU1 GETCHR BADCHR YESNO CPOPJ1 CPOPJ

;Output a string to current network connection.  Call:
;	MOVEI A,[ASCIZ/string/]
;	PUSHJ P,NETSTR
;	<error return>
;	<normal return>
;Clobbers 0 and A.
NETSTR:	HRLI A,440700		;Make byte ptr
NETST1:	ILDB 0,A		;Get char
	JUMPE 0,CPOPJ1		;All done
	PUSHJ P,NETOCH		;Send char
	 POPJ P,		;Error return
	JRST NETST1

;Numeric output routines.  Call with number in A, clobbers A, B, C.
DECOUT:	SKIPA C,[=10]		;Decimal
OCTOUT:	MOVEI C,=8		;Octal
OCTOU1:	IDIVI A,(C)
	HRLM B,(P)
	JUMPE A,.+2
	PUSHJ P,OCTOU1
	HLRZ B,(P)
	ADDI B,"0"
	OUTCHR B
	POPJ P,

;Get single character response from terminal, and begin new line.
;Returns char in 0.
GETCHR:	INCHRW 0		;Get char
	CAIE 0,15		;Return?
	JRST [	OUTSTR CRLF	;No
		CAIL 0,"a"	;Check for lower case
		CAILE 0,"z"
		POPJ P,
		SUBI 0,"a"-"A"	;Convert to upper case
		POPJ P,]
	INCHRW 0		;Yes, read line feed
;Enter here to try again after bad response.
BADCHR:	OUTSTR [ASCIZ/Huh?  Please try again: /]
	JRST GETCHR

;Wait for terminal response; skip if "Y" typed.  Clobbers 0.
YESNO:	PUSHJ P,GETCHR
	CAIE 0,"Y"
	CAIN 0,"y"
CPOPJ1:	AOS (P)
CPOPJ:	POPJ P,
;⊗ MESTYP MESTY1 MAILMS ERRERR

;Error message handler.  Generally the MESSAG macro is used on errors, which
;causes a jump to here.  This then does a POPJ P, which indicates to the next
;level up that there was an error.

MESTYP:	OUTSTR (A)		;Type error message on terminal
	HRLI A,440700		;Make byte ptr
	SKIPGE ERRORS		;Have there been previous errors?
	JRST MESTY1		;Yes, add current text to output
	SETOM ERRORS		;No, this is the first time we're here
	PUSH P,A		;Save ptr while we output header
	INIT ERR,0		;Open error file
	 SIXBIT/DSK/
	 ERBUF,,0
	 JRST ERRERR
	MOVE 0,ERRPPN
	MOVEM 0,ERRFIL+3
	ENTER ERR,ERRFIL
	 JRST ERRERR
	MOVE A,[POINT 7,MAIHD1]
	PUSHJ P,MESTY1		;Output first part of header
	MOVE A,[POINT 7,MAIHD2]
	PUSHJ P,MESTY1		;Second part
	MOVE A,[POINT 7,MAIHD3]
	PUSHJ P,MESTY1		;Third part
	POP P,A			;Now output message
MESTY1:	ILDB 0,A
	JUMPE 0,CPOPJ
	SOSG ERBUF+2
	OUT ERR,
	CAIA
	JRST ERRERR
	IDPB 0,ERBUF+1
	JRST MESTY1

;Here to mail accumulated error text.
MAILMS:	RELEAS ERR,		;Write out error file
	MOVE 14,ERRFIL		;Set input filename for MAIL
	MOVE 13,ERRFIL+1
	MOVE 11,ERRPPN
	MOVEI 12,0		;No returned message
	MOVEI 0,MAIBLK
	SWAP 0,			;Swap to mail
	POPJ P,			;Return if we get back somehow

;Here for error within an error
ERRERR:	OUTSTR [ASCIZ/Error in writing error file!
/]
	HALT .
;⊗ VERNIC VERNI1 VERNI2

;Get version string from the NIC Host Name Server.  Call:
;	PUSHJ P,VERNIC
;	<error return>
;	<success, version string in NICVER>
VERNIC:	MOVE A,[SRINIC]		;Set host number for NETWRK
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT		;Call NETWRK subroutine
	 MESSAG Can't connect to NIC for version request.
	 MESSAG Can't connect to NIC for version request.
	MOVEI A,[ASCIZ/VERSION
/]
	PUSHJ P,NETSTR		;Send a version request
	 MESSAG Error in sending version request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending version request.
	;Now read in characters until connection closes.
	MOVE C,[POINT 7,NICVER]	;Ptr to start depositing chars
VERNI1:	PUSHJ P,NETICW		;Get a char
	 JRST [	TRNN 0,IODEND	;Connection closed?
		MESSAG I/O error in version request reply.
		JRST VERNI2]
	IDPB 0,C		;Store char
	CAMN C,[POINT 7,NICVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version request reply.
	JRST VERNI1		;Back for more

VERNI2:	MOVEI 0,0		;End with a null
	IDPB 0,C
	PUSHJ P,CLOSER		;Call NETWRK to close connection
	JRST CPOPJ1		;And take success return
;⊗ VERIN VERIN1 VERIN2 VEROUT VEROU1 VEROU2

;Get version string of current NIC host table on disk.  Call:
;	PUSHJ P,VERIN
;	<error return>
;	<success, version string in DSKVER>
VERIN:	SETZM DSKVER		;In case LOOKUP fails
	INIT DVER,0
	 SIXBIT/DSK/
	 DVOBUF,,DVIBUF
	 MESSAG INIT error for version file input.
	MOVE A,VERPPN
	MOVEM A,VERFIL+3
	LOOKUP DVER,VERFIL
	 JRST CPOPJ1		;If no version file, just return
	MOVE C,[POINT 7,DSKVER]	;Ptr to start depositing chars
VERIN1:	SOSG DVIBUF+2
	IN DVER,
	 JRST VERIN2
	GETSTS DVER,A
	TRNN A,IODEND		;End of file?
	MESSAG Input error on version file.
	TDZA 0,0		;End with a null
VERIN2:	ILDB 0,DVIBUF+1
	IDPB 0,C
	JUMPE 0,CPOPJ1		;Null or EOF marks end
	CAMN C,[POINT 7,DSKVER+BUFLEN-1,34] ;Check for overflow
	MESSAG Buffer overflow in version file input.
	JRST VERIN1		;Back for more

;Output NIC version string to the file.  Call:
;	<call VERIN; leave DVER channel open>
;	 ...
;	PUSHJ P,VEROUT
;	<error return>
;	<success return>
VEROUT:	MOVE B,VERPPN
	MOVEM B,VERFIL+3
	ENTER DVER,VERFIL	;Open in Read-Alter mode
	 MESSAG ENTER error for version file output.
	USETO DVER,0		;Position at beginning
	MOVE C,[POINT 7,NICVER]
VEROU1:	ILDB 0,C
	JUMPE 0,VEROU2		;Check for end
	SOSG DVOBUF+2
	OUT DVER,
	CAIA
	MESSAG Output error on version file.
	IDPB 0,DVOBUF+1
	JRST VEROU1

VEROU2:	RELEAS DVER,		;Put file in place
	JRST CPOPJ1
;⊗ VERCOM VERCO1

;Compare version strings stored in NICVER and DSKVER.  Call:
;	PUSHJ P,VERCOM
;	<return if the same>
;	<return if different>
VERCOM:	MOVE C,[POINT 7,NICVER]	;Set byte pointers
	MOVE D,[POINT 7,DSKVER]
VERCO1:	ILDB A,C		;Get a byte from each string
	ILDB B,D
	JUMPE A,[JUMPN B,CPOPJ1	;Exit if at end of first string
		 POPJ P,]
	JUMPE B,CPOPJ1		;Or second
	CAIN A,(B)		;Compare
	JRST VERCO1		;Keep checking
	JRST CPOPJ1		;Different
;⊗ NEWNIC NEWNI1 NEWNI2 NEWNI3

;Read in a new table from NIC Host Name Server.  Call:
;	PUSHJ P,NEWNIC
;	<error return>
;	<success>
NEWNIC:	MOVE A,[SRINIC]		;Set host number
	MOVEM A,HOST
	MOVEI A,HNSPRT		;And port number
	MOVEM A,ICPSKT
	PUSHJ P,CONECT
	 MESSAG Can't connect to NIC for host table request.
	 MESSAG Can't connect to NIC for host table request.
	MOVEI A,[ASCIZ/ALL
/]
	PUSHJ P,NETSTR		;Ask for the whole table
	 MESSAG Error in sending host table request.
	PUSHJ P,NETSND		;Force output out
	 MESSAG Error in sending host table request.

	INIT DOUT,0		;Get ready to write new file
	 SIXBIT/DSK/
	 DOBUF,,0
	 MESSAG INIT error for host table output.
	MOVE A,HSTPPN
	MOVEM A,HSTFIL+3
	ENTER DOUT,HSTFIL
	 MESSAG ENTER error for host table output.
	MOVEI A,346		;Lowcore pointer for optimal number of buffers
	PEEK A,
	HLRZ A,A
	OUTBUF DOUT,(A)
	MOVEI C,0		;Initialize byte count
	MOVEI E,ENDMK		;Initialize endmark tester

NEWNI1:	PUSHJ P,NETICW		;Get a character from the network
	 JRST [ TRNN 0,IODEND	;Test for connection close
		MESSAG I/O error in host table request reply.
		JRST NEWNI3]
	SOSG DOBUF+2		;Output the character
	OUT DOUT,
	 CAIA
	MESSAG Output error in writing host table file.
	IDPB 0,DOBUF+1
	SKIPGE E		;Skip unless already seen endmark
	AOJA C,NEWNI1		;Go back for more
	CAMN 0,(E)		;Compare current char to next in endmark
	AOJA E,NEWNI2		;If same, set up for next char
	MOVEI E,ENDMK		;If different, start test at beginning
	AOJA C,NEWNI1		;Go back for more

NEWNI2:	CAIN E,ENDEND		;Matched entire endmark?
	SETOM E			;Yes, note this
	AOJA C,NEWNI1		;And go finish input

NEWNI3:	OUT DOUT,		;Do last output
	 CAIA
	MESSAG Output error in writing host table file.
	SKIPL E			;Was endmark seen?
	MESSAG Endmark of NIC host table not received.
	RELEAS DOUT,		;Yes, put new file in place
	PUSHJ P,CLOSER		;Close net connection
	JRST CPOPJ1		;And take success return
;⊗ RDPDIR

;Here to read saved version number from PUP network directory on disk.  Call:
;	PUSHJ P,RDPDIR
;	<error return>
;	<success, version number in PUPDSV>
RDPDIR:	INIT DIN,17		;Open disk input in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAGE INIT error for PUP network directory input.
	MOVE A,DIRPPN
	MOVEM A,DIRFIL+3
	LOOKUP DIN,DIRFIL
	 JRST CPOPJ1		;Just return if no file
	IN DIN,[IOWD DIRHLN,DIRHDR ↔ 0]	;Read the header
	 CAIA
	MESSAGE Input error for PUP network directory
	LDB A,VERPTR		;Get version number
	MOVEM A,PUPDSV		;Store as disk version number
	JRST CPOPJ1
;⊗ GETVER GETVE1

;Here to get version number from misc servers on the Ethernet.  Assumes
;our version number is already in PUPDSV.  Call:
;	PUSHJ P,GETVER
;	<error return>
;	<success, highest version number in PUPMSV, host in PUPMHS>
GETVER:	MOVE A,PUPDSV		;Our version
	MOVEM A,PUPMSV		;Is best so far
	INIT PUPVER,15		;Packet mode
	 SIXBIT/PUP/
	 0			;No buffers
	 MESSAG INIT error for PUP version request.
	MTAPE PUPVER,VERLSN	;Listen
	SKIPE VERSTS
	 MESSAG Error in LISTEN MTAPE for PUP version request.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,240		;Set packet type to NetDirVersion
	DPB A,PKTTYP
	MOVE A,PUPDSV		;Get our version number
	DPB A,[POINT 16,PKTBFD,15] ;Store in packet
	MOVEI A,PUPOVH+2	;Length = overhead + 2 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP version request output.
	MOVEI C,5		;Number of seconds to wait for replies
	MOVEI D,1
GETVE1:	MTAPE PUPVER,[10]	;Skip if input available
	 JRST [	SOJL C,CPOPJ1	;We can't wait forever
		SLEEP D,	;Wait one second
		JRST GETVE1]	;Try again
	IN PUPVER,[IOWD PUPMAX,PKTBUF ↔ 0] ;Read packet
	 CAIA
	MESSAG Input error in PUP version reply.
	LDB A,PKTTYP		;Check reply type
	LDB B,[POINT 16,PKTBFD,15] ;And version number
	CAIN A,240		;NetDirVersion?
	CAMGE B,PUPMSV		;At least as good as best so far?
	JRST GETVE1		;No, ignore it
	LDB A,PKTSRC		;Get source of this reply
;;	CAIE A,PRFHST		;Is this the preferred host?
	CAMLE B,PUPMSV		;No.  Then we want a higher version number
	CAIA			;Preferred host or higher than current version
	JRST GETVE1		;Reject this one
	MOVEM A,PUPMHS		;Save host number
	MOVEM B,PUPMSV		;This is the best version now
	LDB A,PKTDST		;Get our own address while we're at it
	MOVEM A,OURHST		;We'll need it later
	JRST GETVE1		;Keep trying until tired
;⊗ GNPDIR GNPDI1 GNPDI2 GNPDI4 GNPDI3 GETCOR GETCO1

;Here to get new PUP network directory from host in PUPMHS.  Call:
;	PUSHJ P,GNPDIR
;	<error return>
;	<success return>
;As an undocumented feature, the last 16-bit word of the directory is
;known to contain the PUP checksum of the other words, which we check.
GNPDIR:	INIT PUPEFT,13		;EFTP mode
	 SIXBIT/PUP/
	 0,,PUPIBF
	 MESSAG INIT failure for EFTP channel.
	MOVEI A,=16		;Change byte size
	DPB A,[POINT 6,PUPIBF+1,11] ;in buffer header
	INBUF PUPEFT,2		;Set up buffer ring
	MOVE A,PUPMHS		;Set host number in MTAPE blocks
	MOVEM A,VERHST
	MOVEM A,EFTHST
	MTAPE PUPEFT,EFTGEN	;Gensym a socket for EFTP
	MOVE A,EFTGSK		;Copy into listen block
	MOVEM A,EFTLSK
;debug
	outstr [asciz/EFTP socket number /]
	pushj p,octout
	outstr crlf
;end debug
	MTAPE PUPEFT,EFTLSN	;Listen on EFTP channel
	SKIPE EFTSTS		;Check status bits
	MESSAG Error in LISTEN MTAPE for PUP directory update.
	MTAPE PUPVER,VERTRM	;Close previous connection on PUPVER
	MTAPE PUPVER,VERCON	;Get new connection to this host
	SKIPE VCNSTS
	MESSAG Error in CONNECT MTAPE for PUP directory update.
	SETZM PKTBUF		;Clear out old header, so WAITS fills this
	MOVE A,[PKTBUF,,PKTBUF+1] ;stuff in.
	BLT A,PKTBFD
	MOVEI A,241		;Packet type SendNetDir
	DPB A,PKTTYP
	MOVE A,OURHST			;Our host number
	DPB A,[POINT 16,PKTBFD,15]	;is first part of port number
	MOVE A,EFTGSK			;EFTP socket
	DPB A,[POINT 16,PKTBFD+1,15]	;is the rest
	LSH A,-=16
	DPB A,[POINT 16,PKTBFD,31]
	MOVEI A,PUPOVH+6	;Length = overhead + 6 data bytes
	DPB A,PKTLEN
	ADDI A,2+2+3		;Plus Ethernet header plus rounding
	LSH A,-2		;Convert to words
	HRLOI A,-1(A)		;<len-1>,,-1
	EQVI A,PKTBUF-1		;<-len>,,PKTBUF-1
	SETZ B,			;End IOWD list
	OUT PUPVER,A		;Send the packet
	 CAIA
	MESSAG Error in PUP directory request output.
	RELEAS PUPVER,		;Done with version request channel
	;Now EFTP the directory into core.
	MOVE A,JOBFF↑
	PUSHJ P,GETCOR		;Clear core, set C to bytes cleared
	HRRZ B,JOBFF↑		;Start storing here
	HRLI B,(<POINT 16,0>)	;Make byte ptr to IDPB
	SETZB A,D		;Accumulate checksum in D
GNPDI1:	SOSG PUPIBF+2		;See if there's more EFTP input
	IN PUPEFT,
	 CAIA			;Yes, there is
	JRST GNPDI4		;No, check for end
	ADD D,A			;Add previous byte to checksum
	TRZE D,1B19		;Zero overflow bit, skip if it wasn't set
	AOJ D,			;Add in overflow bit to simulate 1's-complement
	LSH D,1			;Shift bits left
	TRZE D,1B19		;Skip if overflow bit not set, zero it
	AOJ D,			;Add it in on right
	SOJGE C,GNPDI3		;Jump if there's room for next byte
	MOVEI A,1(B)		;No room.  Get address of next word to store
	PUSHJ P,GETCOR		;Get and clear some core
	SOS C			;Fix byte count
GNPDI3:	ILDB A,PUPIBF+1		;Load byte
	IDPB A,B		;Store byte
	JRST GNPDI1		;Continue copying

GNPDI4:	STATO PUPEFT,IODEND	;End of input?
	 MESSAG Error in PUP directory input.
	RELEAS PUPEFT,		;Yes, all done with EFTP channel
	CAIN D,177777		;See if -0
	SETZ D,			;Make into real 0
repeat 0,<
	;As an undocumented feature, the last 16-bit word of the directory
	;is known to contain the PUP checksum of the other words.  Here we
	;check this to be sure we got the directory intact.
	PUSH P,B		;Save ptr to last byte
	TLNE B,200000		;Does last word have 1 byte?
	TDZA C,C		;Yes, set C=0
	MOVEI C,1		;No, set C=1
	HRRZ B,B		;Compute number of PDP-10 words
	SUB B,JOBFF↑		; not counting last word
	LSH B,1			;Convert to number of 16-bit bytes
	ADDI B,(C)		;Include last word, minus checksum byte
	MOVE A,JOBFF↑		;Addr of table
	PUSHJ P,PUPCHK		;Now compute checksum
>;repeat 0
;;	CAIE A,(D)		;Compare last byte with checksum
;;	MESSAG Checksum of network directory failed
;debug
	CAIN A,(D)
	 JRST ..TMP1
	PUSH P,B
	PUSH P,C
	OUTSTR [ASCIZ/Checksum of network directory failed, last word = /]
	PUSHJ P,OCTOUT
	OUTSTR [ASCIZ/, checksum = /]
	POP P,A
	PUSHJ P,OCTOUT
	OUTSTR [ASCIZ/.
Storing directory anyway.
/]
	POP P,B
..TMP1:
;end debug
	INIT DOUT,17		;Open disk output channel in dump mode
	 SIXBIT/DSK/
	 0
	 MESSAG Disk INIT failure in writing PUP directory.
	MOVE A,DIRPPN		;Set up ENTER block
	MOVEM A,DIRFIL+3
	ENTER DOUT,DIRFIL	;Enter directory file
	 MESSAG ENTER error in writing PUP directory.
	HRRZ A,JOBFF↑		;Addr of start of data
	SUBI A,1		;-1 for IOWD
	SUBM A,B		;-<word count> in RH(B)
	HRL A,B			;Make IOWD
	SETZ B,			;End IOWD list
	OUT DOUT,A		;Do dump mode output
	 CAIA
	MESSAGE Output error in writing PUP directory file.
	RELEAS DOUT,
	JRST CPOPJ1		;All done, hooray!

;Here to clear core and expand if necessary.
;Call:	MOVE A,<starting address of core to clear>
;	PUSHJ P,GETCOR
;	<return with core cleared from (A) to JOBREL, byte count in C>
GETCOR:	CAMGE A,JOBREL↑		;Need more core?
	JRST GETCO1		;No.  (Must be first call to GETCOR)
	MOVEI C,1777(A)		;Yes, get 2 pages
	CORE C,
	 MESSAG CORE UUO failed in PUP directory input.
GETCO1:	SETZM (A)		;Zero first word
	MOVEI C,1(A)		;Make BLT word
	HRLI C,(A)
	BLT C,@JOBREL↑		;Clear core
	MOVE C,JOBREL↑
	SUBI C,-1(A)		;Count of words gotten
	LSH C,1			;Times 2 for 16-bit bytes
	POPJ P,

repeat 0,<
;PUP checksum algorithm, used to check validity of net directory.  Call:
;	MOVE A,<address of first 16-bit byte>
;	MOVE B,<number of 16-bit bytes>
;	PUSHJ P,PUPCHK
;	<return with C = checksum>
;Clobbers A, B, C, D.
PUPCHK:	HRLI A,(<POINT 16,0>)	;Make byte ptr
	SETZ C,			;Use to accumulate checksum
PUPCK1:	ILDB D,A		;Get a 16-bit word
	ADD C,D			;Add it to checksum
	TRZE C,1B19		;Zero overflow bit, skip if it wasn't set
	 AOJ C,			;Add in overflow bit to simulate 1's-complement
	LSH C,1			;Shift bits left
	TRZE C,1B19		;Skip if overflow bit not set, zero it
	 AOJ C,			;Add it in on right
	SOJG B,PUPCK1		;Go until we are done
	CAIN C,177777		;See if -0
	SETZ C,			;Make into real 0
	POPJ P,
>;repeat 0
;⊗ NICUPD NICUP1 NICERR

NICUPD:	MOVEI 0,"U"		;Default option for batch job
	SKIPE BATCHM
	JRST NICUP1
	OUTSTR [ASCIZ/
Type U to update NIC table if necessary,
     F to force update,
     C to check version,
     S to skip NIC table processing
Choose one: /]
	PUSHJ P,GETCHR
	CAIN 0,"S"
	POPJ P,
	CAIE 0,"U"		;Check for legality
	CAIN 0,"F"
	JRST NICUP1
	CAIN 0,"C"
	JRST NICUP1
	PUSHJ P,BADCHR
	JRST NICUPD

NICUP1:	OUTSTR [ASCIZ/Getting latest version number from NIC name server.
/]
	PUSHJ P,VERNIC		;Get NIC directory version string
	 JRST NICERR		;Error of some kind
	OUTSTR [ASCIZ/NIC's version string is /]
	OUTSTR NICVER
	OUTSTR CRLF
	PUSHJ P,VERIN		;Get version from disk file
	 JRST NICERR		;Error
	OUTSTR [ASCIZ/Saved version string is /]
	OUTSTR DSKVER
	OUTSTR CRLF
	PUSHJ P,VERCOM		;Compare version strings
	 JRST [	OUTSTR [ASCIZ/No update of NIC host table needed.
/]
		SKIPE BATCHM
		POPJ P,
		OUTSTR [ASCIZ/Update it anyway?/]
		PUSHJ P,YESNO
		 POPJ P,
		JRST .+1]
	OUTSTR [ASCIZ/Getting new host table from NIC name server.
/]
	PUSHJ P,NEWNIC		;Read in the new host table
	 JRST NICERR		;Some error
	PUSHJ P,VEROUT		;Output version string to file
	 JRST NICERR		;Some error
	OUTSTR [ASCIZ/New host table successfully installed.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

NICERR:	RELEAS DVER,3		;Don't write any files!
	RELEAS DOUT,3
	POPJ P,
;⊗ PUPUPD PUPERR

PUPUPD:	SKIPE BATCHM		;Batch job always checks PUP table
	JRST PUPUP1
	OUTSTR [ASCIZ/Do PUP table update?/]
	PUSHJ P,YESNO
	 POPJ P,
PUPUP1:	PUSHJ P,RDPDIR		;Read version from PUP directory on disk
	 JRST PUPERR		;Error
	OUTSTR [ASCIZ/Our PUP network directory is version /]
	MOVE A,PUPDSV
	PUSHJ P,OCTOUT
	OUTSTR CRLF
	PUSHJ P,GETVER		;Get version from misc servers
	 JRST PUPERR		;Error of some kind
	MOVE A,PUPMSV		;Highest version reported
	CAMG A,PUPDSV		;Compare with our version
	 JRST [	OUTSTR [ASCIZ/No update of PUP network directory needed.
/]
		POPJ P,]
	OUTSTR [ASCIZ/Getting new PUP directory version /]
	PUSHJ P,OCTOUT		;Output version in A
	OUTSTR [ASCIZ/ from host /]
	LDB A,[POINT 8,PUPMHS,27]
	PUSHJ P,OCTOUT		;Subnet
	OUTCHR ["#"]
	LDB A,[POINT 8,PUPMHS,35]
	PUSHJ P,OCTOUT		;Host
	OUTSTR CRLF
	PUSHJ P,GNPDIR		;Get new PUP directory
	 JRST PUPERR		;Some error
	OUTSTR [ASCIZ/New PUP directory successfully installed.
/]
	SETOM CHANGE		;Indicate change
	POPJ P,

PUPERR:	RELEAS DOUT,3		;Don't write file
	POPJ P,
;⊗ UPDATE NOERRS

;Main program

TABLES:	TDZA A,A		;Normal start
	MOVNI A,1		;Batch mode start
	MOVEM A,BATCHM
	RESET
	MOVE P,[IOWD PDLEN,PDL]
	PUSHJ P,NICUPD		;Update NIC table
	SKIPE BATCHM		;Make batch output look pretty
	OUTSTR [ASCIZ/--------------------------------------------------
/]
	PUSHJ P,PUPUPD		;Update PUP table
	SKIPN BATCHM
	EXIT			;All done if not batch mode
	SKIPN ERRORS		;Were there errors?
	JRST NOERRS
	MOVEI A,[ASCIZ/UPDATE aborted due to errors.
/]
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS		;Mail errors to interested people
	EXIT

NOERRS:	SKIPN CHANGE		;Did anything change?
	EXIT			;No, all done
;Temporary, until we're fully automated
	OUTSTR CRLF
	MOVEI A,[ASCIZ/New NIC or PUP table installed.  Please check the log, and run PUPHST if
necessary, and HOSTS3.
/]
	PUSHJ P,MESTYP
	PUSHJ P,MAILMS
;End temporary code
	EXIT

	END TABLES